--[[
    ManyItemTooltips 3.0
    By Doomchicken of Dark Iron[US}
    Add support for MIT to your addon! See bottom of code.
    :D
]]

local presetHooks = {
    TooltipItemIcon = { "OnShow", function(frame) TooltipItemIcon_DisplayIcon(frame, MIT:GetLinkString(frame)) end },
    IDCard = { "OnCreate", function(frame) IDCard:RegisterTooltip(frame) end },
    Valuation = { "OnShow", function(frame) if (Valuation["styles"][ValuationCfg["style"]]) then Valuation["styles"][ValuationCfg["style"]].Draw(frame, GetSellValue(MIT:GetLinkString(frame)), 1) end end },
    StatStain = { "OnCreate", function(frame) LibStub("AceAddon-3.0"):GetAddon("StatStain"):AddTooltip(frame) end }
}
local tooltipTypes = {
    item = true,
    spell = true,
    achievement = true,
    quest = true,
    enchant = true,
    talent = true,
}

MIT = CreateFrame("Frame")
MIT:RegisterEvent("VARIABLES_LOADED")

local hooks = { }
local tooltips = { }
local links = { }

local wotlk = select(4,GetBuildInfo()) >= 30000

local function onEvent(self, event, addon)
    if event == "ADDON_LOADED" then
        if presetHooks[addon] and not hooks[addon] then
            self:AddHook(addon, presetHooks[addon][1], presetHooks[addon][2])
        end
    else
        hooksecurefunc(ItemRefTooltip, "Hide", function() links["ItemRefTooltip"] = nil end)
        for i,v in pairs(presetHooks) do
            if IsAddOnLoaded(i) and not hooks[i] then
                self:AddHook(i, v[1], v[2])
            end
        end
        self:RegisterEvent("ADDON_LOADED")
    end
end
MIT:SetScript("OnEvent", onEvent)

local function checkHook(event, frame)
    for i,v in pairs(hooks) do
        if v[event] then
            v[event](frame)
        end
    end
end

local OldOnHyperlinkShow = ChatFrame_OnHyperlinkShow
-- Our replacement function
ChatFrame_OnHyperlinkShow = function(...)
    local self, link, text, button = ...
    
    -- Don't mess with modified clicks
    if IsModifiedClick("CHATLINK") then
        return OldOnHyperlinkShow(...)
    end
    
    -- Check if it's an item / profession link
    local linkType 
    if not wotlk then
        linkType = strmatch(link, "^.+|H(%w+):.+")
    else
        linkType = strmatch(link, "^(%w+):")
    end
    if not tooltipTypes[linkType] then
        return OldOnHyperlinkShow(...)
    end
    
    -- Check shown tooltips (and close if it matches)
    local isShown = MIT:IsLinkShown(link)
    if isShown then
        return MIT:HideFrame(getglobal(isShown))
    end
    
    -- ItemRef not shown? Use it first
    if not ItemRefTooltip:IsVisible() then
        links["ItemRefTooltip"] = link
        return OldOnHyperlinkShow(...)
    end
    
    MIT:ShowFrame(MIT:GetAvailableFrame(), link)
end

function MIT:ShowFrame(frame, link)
    ShowUIPanel(frame)
    if not frame:IsShown() then
        frame:SetOwner(UIParent, "ANCHOR_PRESERVE")
    end
    frame:SetHyperlink(link)
    links[frame:GetName()] = link
    checkHook("OnShow", frame)    
end

function MIT:HideFrame(frame)
    HideUIPanel(frame)
    checkHook("OnHide", frame)
end

function MIT:GetAvailableFrame()
    for i,v in ipairs(tooltips) do
        if not v:IsVisible() then
            return v
        end
    end
    return self:CreateTooltip()
end

-- Returns the link string (I don't think it's possible through blizzard code to get profession, etc strings)
function MIT:GetLinkString(frame)
    return links[(type(frame) == "string" and frame) or frame:GetName()]
end

function MIT:IsLinkShown(link)    
    for i,v in pairs(links) do
        if v == link then
            return i
        end
    end
    return nil
end

function MIT:CreateTooltip(link)
    local n = #tooltips+1
    local name = "ItemRefTooltip"..n+1 -- Support for TipHooker and mods that support MultiTips (limited up to 5)
    local frame = CreateFrame("GameTooltip", name, UIParent, "MIT_Tooltip_Template")
    tinsert(UISpecialFrames, name)
    hooksecurefunc(frame, "Hide", function() links[name] = nil end)
    if link then
        self:ShowFrame(frame, link)
    end
    tooltips[n] = frame
    checkHook("OnCreate", frame)
    return frame
end

-- To AddOn Authors: Thanks for your interest in adding support for MIT to your addon!
-- Usage: MIT:AddHook("MyAddOn", "OnShow", function(frame) MyAddon:DoSomething(frame) end)
-- Events: OnShow, OnHide, OnCreate
function MIT:AddHook(name, event, func)
    hooks[name] = hooks[name] or { }
    hooks[name][event] = func
end

-- Backwards compatibility (don't use please, may be removed in the future)
function MIT_AddHook(event, func)
    hooks[#hooks+1] = { }
    hooks[#hooks][event] = func
end

--2.4.3 patch
function MIT_GetHyperlink(object)
    return links[object:GetName()]
end
